/*****************************************************************
Mix3D WebGL Game Engine
Copyright (c) fantasy ( fantasy.x2x@gmail.com )
Listens:
Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt
 ****************************************************************/
/**
 * @Desc    : resource
 * @Author  : fantasy(fantasy.x2x@gmail.com)
 */
//////////////////////////////////////////////////////////////////
if(typeof(Mix3D) === 'undefined')
{
  Mix3D = {};
};
(function(Mix3D){
//////////////////////////////////////////////////////////////////
//
//            Resource abstract
//
//////////////////////////////////////////////////////////////////
Mix3D.Resource = function()
{
  this.name = '';
  this.callback = [];
  this.isRequest = false;
};

Mix3D.protoCopy(Mix3D.Object, Mix3D.Resource);

Mix3D.Resource.prototype.className = 'Resource';

Mix3D.Resource.prototype.setResName = function(name) { this.name = name; };

Mix3D.Resource.prototype.request = function(callback) 
{
  if(!this.isReady())
  {
    if(callback)this.callers.push(callback);
    if(!this.isRequest)
    {
      this.isRequest = true;
      this.create();
    }
  }
  else if(callback !== undefined)
  {
    callback(this);
  } 
  return this;
};
Mix3D.Resource.prototype.onReady = function()
{
  while(this.callers.length>0)
  {
     var callBack = this.callers.pop();
     callBack(this.res);
  }
};
//work interface
Mix3D.Resource.prototype.isReady = function(){ return false; };
Mix3D.Resource.prototype.create = function() {};
Mix3D.Resource.prototype.release = function(){};
Mix3D.Resource.prototype.load = function(stream) {};
Mix3D.Resource.prototype.save = function(stream) {};

//////////////////////////////////////////////////////////////////
//
//            Resource Manager
//
//////////////////////////////////////////////////////////////////
Mix3D.ResourceManager = (function()
{
  var that = {};
  var resGroup = {};
  var stream = new Mix3D.Archive();
  
  ResourceGroup = function(resType)
  {
    this.resType = resType;
    this.resArray =[];
    this.resMap = {};
    this.has = function( name )
    {
      return this.resMap[name]!==undefined;
    };
    this.add = function( res )
    {
      if(this.resMap[name]===undefined)
      {
        var i, len;
        for( i=0,len=this.resArray.length; i<len; ++i)
        {
          if(this.resArray[i] === null)
          {
            this.resArray[i] = res;
            break;
          }
        }
        if( i === len)
        {
          this.resArray.push[res];
        }
        this.resMap[name] = i;
      }
      else
      {
        Mix3D.warning("the resource exsit of group [ "+ resType + " ], [ "+ name + " ]");
      }
    };
    this.remove = function(name)
    {
      var idx = this.resMap[name];
      if(idx!==undefined)
      {
        this.resArray.split(idx, 1);
        this.resMap[name]=undefined;
      }
      else
      {
        Mix3D.warning("the resource is't exsit of group [ "+ resType + " ]");
      }
    };
    this.get = function( name )
    {
      var idx = this.resMap[name];
      if(idx!==undefined)
      {
        return this.resArray[idx];
      }
      return undefined;
    };
  };
/**
 *  resource type register
 **/
  that.regResourceType = function(resClass )
  {
    if(resClass.prototype.className === undefined)
    {
      Mix3D.warning("regResourceType : the resource class name undefined");
      return;
    }
    var type = resClass.prototype.className;
    
    if(resGroup[type] === undefined)
    {
      var group = new ResourceGroup(type);
      group.classType =resClass.prototype;
      resGroup[type] = group;
      resClass.prototype.__resGroup = group;
      resClass.prototype.request = function(name, callback)
      {
        return that.request(this.className, name, callback);
      };
    }
  };
/**
 *  resource instance register
 **/
  that.regResourceIns = function( res )
  {
    if(!res.name || res.name=== '')
    {
      Mix3D.error("Mix3D.ResourceManager.regResourceIns : the resource name must be define, can't be null");
      return;
    }
    var group = res.__resGroup;
    if(group)
    {
      group.add(res);
    }
    else
    {
      Mix3D.error("Mix3D.ResourceManager.regResourceIns : the resource type unregister! [ " +res.resType + " ]");
    }
  };
/**
 *  Resource desc restister
 **/
  that.regResourceDesc = function( resType, name, data)
  {
    var group = resGroup[resType];
    if(group)
    {
      var classProto = group.classType;
      if(classProto)
      {
        var res = new Mix3D[resType];
        stream.clear().parse(data);
        res.load(stream);
        this.register(res);
        return;
      }
    }

    Mix3D.error("Mix3D.ResourceManager.registerDesc : the resType[ " +resType + " ] is't exsit!");
  };
  
  that.search = function( resType, name )
  {
    var res = undefined;
    var group = resGroup[resType];
    if(group)
    {
      res = group.get(name);
      if(!res)
      {
        Mix3D.warning("can't find resource --- [ " + resType + " ]" + name);
      }
    }
    return res;
  };
  
  that.loadResDefines = function( url, callback)
  {
    archive.load(url, callback);
  };

  that.request = function( resType, name, callback)
  {
    var res = this.search(resType,name);
    if(res)
    {
      res.request(callback);
    }
    return res;
  };
  
  that.release = function( resType, name )
  {
    var res = this.search(resType, name );
    if(res)
    {
      res.release();
      delete res;
    } 
  };
  
  return that;
}());//end of Mix3D.ResourceManager

Mix3D.defineResourceType = function(res)
{
  Mix3D.ResourceManager.regResourceType(res);
};
//////////////////////////////////////////////////////////////////
})(Mix3D);// end of function(Mix3D)